/**
 * create by zhike date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.baofup.marshall;

import com.acooly.core.utils.Reflections;
import com.acooly.core.utils.Strings;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.baofup.BaoFuPConstants;
import com.acooly.module.openapi.client.provider.baofup.domain.BaoFuPResponse;
import com.acooly.module.openapi.client.provider.baofup.enums.BaoFuPServiceEnum;
import com.acooly.module.openapi.client.provider.baofup.exception.BaoFuPApiClientProcessingException;
import com.acooly.module.openapi.client.provider.baofup.support.BaoFuPAlias;
import com.acooly.module.openapi.client.provider.baofup.utils.BaoFuPSecurityUtil;
import com.acooly.module.openapi.client.provider.baofup.utils.StringHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * @author zhike
 */
@Service
@Slf4j
public class BaoFuPResponseUnmarshall extends BaoFuPMarshallSupport
        implements ApiUnmarshal<BaoFuPResponse, String> {

    @Resource(name = "baoFuPMessageFactory")
    private MessageFactory messageFactory;

    @SuppressWarnings("unchecked")
    @Override
    public BaoFuPResponse unmarshal(String responseInfo, String serviceName) {
        try {
            if (Strings.isBlank(responseInfo)) {
                log.info("请求失败:响应报文为空");
                throw new ApiClientException("请求失败:响应报文为空");
            }
            try {
                log.info("响应报文:{}", responseInfo);
            } catch (Exception e) {
                throw new BaoFuPApiClientProcessingException("解析响应报文错误:" + e.getMessage());
            }
            Map<String, String> resMessageMap = StringHelper.getResponseParm(responseInfo);
            String signature = resMessageMap.get(BaoFuPConstants.SIGNER_TYPE);
            String partnerId = resMessageMap.get(BaoFuPConstants.PARTNER_KEY);
            resMessageMap.remove(BaoFuPConstants.SIGNER_TYPE);
            //验签
            String rSignVStr = StringHelper.coverMap2String(resMessageMap);
            log.info("响应报文SHA-1摘要字串：{}", rSignVStr);
            String rSignature = BaoFuPSecurityUtil.sha1X16(rSignVStr, "UTF-8");
            log.info("响应报文SHA-1摘要结果：" + rSignature);
            doVerify(signature, rSignature, partnerId);
            log.info("验签成功");
            //解密数字信封
            String aesKey = "";
            if (resMessageMap.containsKey(BaoFuPConstants.DGTL_ENVLP)) {
                String dgtlEnvlp = resMessageMap.get(BaoFuPConstants.DGTL_ENVLP);
                String dgtlEnvlpDecode = doDecodeByProvateKey(dgtlEnvlp, partnerId);
                //获取aesKey
                aesKey = StringHelper.getAesKey(dgtlEnvlpDecode);//获取返回的AESkey
            }
            //解析响应报文为实体
            BaoFuPResponse response = doUnmarshall(resMessageMap, serviceName, aesKey);
            return response;
        }catch (Exception e) {
            throw new BaoFuPApiClientProcessingException("解析响应报文异常"+e.getMessage());
        }
    }

    protected BaoFuPResponse doUnmarshall(Map<String,String> resMessage, String serviceName,String aesKey) {
        BaoFuPResponse response =
                (BaoFuPResponse) messageFactory.getResponse(BaoFuPServiceEnum.find(serviceName).getKey());
        Set<Field> fields = Reflections.getFields(response.getClass());
        String key = null;
        for (Field field : fields) {
            Object convertedValue = null;
            BaoFuPAlias baoFuPAlias = field.getAnnotation(BaoFuPAlias.class);
            if (baoFuPAlias != null && Strings.isNotBlank(baoFuPAlias.value())) {
                key = baoFuPAlias.value();
            } else {
                key = field.getName();
            }
            convertedValue = resMessage.get(key);
            if(Strings.isNotBlank((String)convertedValue)) {
                //解密
                boolean isDecode = baoFuPAlias.isDecode();
                if (isDecode) {
                    convertedValue = BaoFuPSecurityUtil.Base64Decode(BaoFuPSecurityUtil.AesDecrypt((String)convertedValue,aesKey));
                }
                Reflections.invokeSetter(response, field.getName(), convertedValue);
            }
        }
        return response;
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }
}
